home *** CD-ROM | disk | FTP | other *** search
/ Floppyshop 2 / Floppyshop - 2.zip / Floppyshop - 2.iso / art&graf.ix / art-3871 / mdl10 / mdl.c < prev    next >
C/C++ Source or Header  |  1993-06-06  |  12KB  |  566 lines

  1. /*
  2.  *    mdl -- display a DL animation (monochrome ST only)
  3.  *
  4.  *    uses Setscreen flicker trick
  5.  *
  6.  *
  7.  *
  8.  *    derived from xdl by:
  9.  *          Jonas Yngvesson <jonas-y@isy.liu.se>
  10.  *
  11.  *    which was derived from dltogl.c by:
  12.  *        George Phillips <phillips@cs.ubc.ca>
  13.  *
  14.  *    Support for user defined animation speed:
  15.  *          Per Beremark <per.beremark@telelogic.se>
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>        /* for malloc */
  20. #include <unistd.h>        /* for getopt */
  21. #include <sys/types.h>
  22. #include <sys/time.h>
  23.  
  24.  
  25. #define isneg16(x)    ((x) & 0x8000)
  26. #define neg16(x)    ((~(x) + 1) & 0x7fff)
  27.  
  28.  
  29. typedef struct {
  30.     int    version;
  31.     int    format;
  32.     int    images_per_screen;
  33.     char    title[21];
  34.     char    author[21];
  35.     int    num_screen;
  36.     int    num_command;
  37. } DL_info;
  38.  
  39.  
  40. int        __default_mode__ = _IOBIN;    /* force stdin binary (gcc) */
  41.  
  42. unsigned long    pixels[256];            /* for colormap conversion */
  43. char           *myname = "mdl";
  44.  
  45. void        usage (int);
  46. void        colormap_setup (FILE *, int);
  47. extern int    dl_flicker (unsigned char *, int, int, int, int, int, int, int, int *, int, int);
  48.  
  49.         /* pimg        -> raster image sequence (intensities) */
  50.         /* nframes    number of frames in pimg */
  51.         /* width    width, pixels */
  52.         /* hight    height, pixels */
  53.         /* beta        for laplace filter */
  54.         /* maxrandom    for random noise */
  55.         /* opt        0=no flicker, 1=flicker */
  56.         /* delay    ms delay between images */
  57.         /* cmd        -> commands (order to display frames) */
  58.         /* numcmd    number of commands */
  59.         /* show        print info to stdout if != 0 */
  60.  
  61.  
  62. extern char    *optarg;                /* getopt stuff */
  63. extern int    optind;
  64.  
  65.  
  66.  
  67. /*------------------------------*/
  68. /*    main            */
  69. /*------------------------------*/
  70. void main (int argc, char *argv[])
  71. {
  72.     DL_info        dlinfo;        /* dl file info */
  73.     char           *filename;
  74.     FILE           *fp;
  75.     unsigned char  *image_data;    /* space for 1 screen from file */
  76.     unsigned char  *img;        /* space for all frames */
  77.     unsigned char  *pimg;        /* ptr to img */
  78.     long        pimg_inc;    /* increment to next frame in img */
  79.     int        nframes;    /* num of individual frames */
  80.     int        ncommands;    /* num of frames (= num frames in loop)*/
  81.     short        gray;
  82.     int        width,
  83.             height;
  84.     int           *cmd;        /* space for command list */
  85.     int        labelpos;
  86.     int        frame_freq;    /* milliseconds per frame */
  87.     int        fps = 25;    /* frames per second */
  88.     int        zoomflag = 0;
  89.     int        ival = 0;
  90.     int        errflg = 0;
  91.     int        do_flick = 1;
  92.     int        beta = 0;
  93.     int        noise = 0;
  94.     int        verbose = 0;
  95.     int        i, j;
  96.  
  97.  
  98.  
  99.     /*
  100.      *   parse command line...
  101.      */
  102.     while ((i = getopt(argc, argv, "vszhr:i:b:n:")) != -1)
  103.     {
  104.         switch (i)
  105.         {
  106.         case 'v':                /* verbose */
  107.             verbose++;
  108.             break;
  109.  
  110.         case 's':                /* single (no flicker)*/
  111.             do_flick = 0;
  112.             break;
  113.  
  114.         case 'b':                /* beta */
  115.             beta = atoi(optarg);
  116.             if (beta < 0) beta = 0;
  117.             break;
  118.  
  119.         case 'n':                /* noise */
  120.             noise = atoi(optarg);
  121.             if (noise < 0)   noise = 0;
  122.             if (noise > 255) noise = 255;
  123.             break;
  124.  
  125.         case 'i':                /* intensity adjust */
  126.             ival = atoi(optarg);
  127.             if (ival < -254) ival = -254;
  128.             if (ival >  254) ival = 254;
  129.             break;
  130.  
  131.         case 'z':                /* zoom */
  132.             zoomflag = 1;
  133.             break;
  134.  
  135.         case 'h':                /* help */
  136.             usage (0);
  137.             break;    /*NOTREACHED*/
  138.  
  139.         case 'r':                /* rate (fps) */
  140.             fps = atoi(optarg);
  141.             if (fps < 1) fps = 1;
  142.             if (fps > 100) fps = 100;
  143.             break;
  144.  
  145.         case '?':
  146.         default:
  147.             errflg++;
  148.         }
  149.     }
  150.     if (errflg)
  151.     {
  152.         usage(2);
  153.     }
  154.  
  155.  
  156.  
  157.     /*
  158.      *   if no files, use stdin. otherwise open file
  159.      */
  160.     if (argv[optind] == NULL)
  161.     {
  162.         fp       = stdin;
  163.         filename = "stdin";
  164.     }
  165.     else if ((fp = fopen (argv[optind], "rb")) == NULL)
  166.     {
  167.         fprintf(stderr, "%s: can't open %s\n", myname, argv[1]);
  168.         exit(1);
  169.     }
  170.     else
  171.     {
  172.         filename = argv[optind];
  173.     }
  174.  
  175.  
  176.  
  177.     /*
  178.      *   Check the version number...
  179.      */
  180.     if ((dlinfo.version = fgetc(fp)) != 1 && dlinfo.version != 2)
  181.     {
  182.         fprintf(stderr, "%s: This file is in an unknown format.\n",
  183.             myname);
  184.         fprintf(stderr, "can only do .DL version 1 and 2 (this is %d).\n",
  185.             dlinfo.version);
  186.         exit(1);
  187.     }
  188.  
  189.     
  190.  
  191.     /*
  192.      *   ...and the format.
  193.      */
  194.     if (dlinfo.version == 1)
  195.         dlinfo.format = 1;
  196.     else
  197.         dlinfo.format = fgetc(fp);
  198.     
  199.     switch (dlinfo.format)
  200.     {
  201.     case 0:                /* large */
  202.         width = 320;
  203.         height = 200;
  204.         dlinfo.images_per_screen = 1;
  205.         zoomflag = 0;
  206.         break;
  207.  
  208.     case 1:                /* medium */
  209.         if (zoomflag)
  210.         {
  211.             width = 320;
  212.             height = 200;
  213.         }
  214.         else
  215.         {
  216.             width = 160;
  217.             height = 100;
  218.         }
  219.         dlinfo.images_per_screen = 4;
  220.         break;
  221.  
  222.     default:
  223.         fprintf(stderr,
  224.             "%s: only large and medium formats are handled",
  225.             myname);
  226.         exit(1);
  227.         break;
  228.     }
  229.     
  230.  
  231.  
  232.     /*
  233.      *   Get title and author (if any). i don't know what this is used
  234.      *   for...
  235.      */
  236.     dlinfo.title[20] = dlinfo.author[20] = 0;
  237.     for (i = 0; i < 20; i++)
  238.     {
  239.         dlinfo.title[i] = fgetc(fp) ^ 255;
  240.         if ((unsigned char)dlinfo.title[i] == 255)
  241.             dlinfo.title[i] = 0;
  242.     }
  243.     for (i = 0; i < 20; i++)
  244.     {
  245.         if (dlinfo.version == 2)
  246.         {
  247.             dlinfo.author[i] = fgetc(fp) ^ 255;
  248.             if ((unsigned char)dlinfo.author[i] == 255)
  249.                 dlinfo.author[i] = 0;
  250.         }
  251.         else
  252.             dlinfo.author[i] = 0;
  253.     }
  254.     
  255.  
  256.  
  257.     /*
  258.      *   Read number of screens and commands.
  259.      */
  260.     dlinfo.num_screen = fgetc(fp);
  261.     dlinfo.num_command = fgetc(fp);
  262.     
  263.  
  264.  
  265.     /*
  266.      *   Display what we know so far.
  267.      */
  268.     nframes   = dlinfo.num_screen * dlinfo.images_per_screen;
  269.     ncommands = dlinfo.num_command;
  270.     if (verbose)
  271.     {
  272.         printf("%s is a %s sized version %d .DL file.\n",
  273.             filename,
  274.             (dlinfo.format == 0 ? "large" : "medium"), 
  275.             dlinfo.version);
  276.         printf("It contains %d images (num_screen=%d * images_per_screen=%d)\n",
  277.             dlinfo.num_screen * dlinfo.images_per_screen,
  278.             dlinfo.num_screen,
  279.             dlinfo.images_per_screen);
  280.         printf("in a %d frame (num_command) loop.\n",
  281.             dlinfo.num_command);
  282.         if (dlinfo.format == 1 && zoomflag)
  283.         {
  284.             puts("Zooming images to 320x200.");
  285.         }
  286.         printf("Displaying animation at %d frames per second.\n",fps);
  287.     }
  288.  
  289.  
  290.  
  291.     /*
  292.      *   do the color map
  293.      */
  294.     if (verbose)
  295.         printf("Reading colormap...\n");
  296.     colormap_setup(fp, dlinfo.version);
  297.  
  298.  
  299.  
  300.     /*
  301.      *   Allocate memory for the commands, the image data, etc
  302.      */
  303.     if (verbose)
  304.         printf ("Allocating memory:\n");
  305.  
  306.     /* command list: */
  307.     if (verbose)
  308.         printf ("   command list (%d bytes)\n",
  309.             dlinfo.num_command * sizeof(int));
  310.     if (!(cmd = (int *)malloc(dlinfo.num_command * sizeof(int))))
  311.     {
  312.         fprintf(stderr, "%s: out of memory (commands)", myname);
  313.         exit(1);
  314.     }
  315.  
  316.     /* one screen (file): */
  317.     if (verbose)
  318.         printf ("   single screen from file (64000 bytes)\n");
  319.     if (NULL == (image_data = (unsigned char *)malloc(320 * 200)))
  320.     {
  321.         fprintf(stderr, "%s: not enough memory (image data).", myname);
  322.         exit(1);
  323.     }
  324.  
  325.     /* all frames: */
  326.     if(dlinfo.format == 0)
  327.     {
  328.         /* large */
  329.         if (verbose)
  330.             printf ("   raster list, large (%ld bytes)\n",
  331.                 (long)(320L * 200L * dlinfo.num_screen));
  332.         img = (unsigned char *)malloc(320 * 200 * dlinfo.num_screen);
  333.         pimg_inc = 320 * 200;
  334.     }
  335.     else if (zoomflag)
  336.     {
  337.         /* medium->large */
  338.         if (verbose)
  339.             printf ("   raster list, zoom (%ld bytes)\n",
  340.                 (long)(320L * 200L * dlinfo.num_screen * dlinfo.images_per_screen));
  341.         img = (unsigned char *)malloc(320 * 200 *
  342.             dlinfo.num_screen * dlinfo.images_per_screen);
  343.         pimg_inc = 320 * 200;
  344.     }
  345.     else
  346.     {
  347.         /* medium */
  348.         if (verbose)
  349.             printf ("   raster list, medium (%ld bytes)\n",
  350.                 (long)(160L * 100L * dlinfo.num_screen * dlinfo.images_per_screen));
  351.         img = (unsigned char *)malloc(160 * 100 *
  352.             dlinfo.num_screen * dlinfo.images_per_screen);
  353.         pimg_inc = 160 * 100;
  354.     }
  355.     if (img == (unsigned char *) NULL)
  356.     {
  357.         fprintf(stderr, "%s: not enough memory (pimg).", myname);
  358.         exit(1);
  359.     }
  360.     pimg = img;
  361.  
  362.  
  363.  
  364.     /*
  365.      *   Build the pixmaps for the animation.
  366.      */
  367.     if (verbose)
  368.     {
  369.         printf("Building pixmaps, wait..."); fflush(stdout);
  370.     }
  371.     for (j = 0; j < dlinfo.num_screen; j++)
  372.     {
  373.         unsigned char  *src;
  374.         int        row;
  375.         int        col;
  376.  
  377.  
  378.         /*
  379.          *   Read one screen of data.
  380.          */
  381.         fread(image_data, 1, 320 * 200, fp);
  382.  
  383.  
  384.         /*
  385.          *   Each screen can hold several images.
  386.          */
  387.         for (i = 0; i < dlinfo.images_per_screen; i++)
  388.         {
  389.             /*
  390.              *   Get a pointer to the beginning of this image.
  391.              *   Put the pixels in the img raster. We do zooming
  392.              *   by reading the same data several times.
  393.              */
  394.             src = image_data + (i % 2) * 160 + (i / 2) * 100 * 320;
  395.  
  396.             for (row = 0; row < height; row++)
  397.             {
  398.                 for (col = 0; col < width; col++)
  399.                 {
  400.                     /*
  401.                      *   map raw data to colormap
  402.                      *   intensity
  403.                      */
  404.                     gray = pixels[*src] + ival;
  405.                     if (gray > 255)    gray = 255;
  406.                     if (gray < 0)    gray = 0;
  407.  
  408.                     /*
  409.                      *   poke in our raster
  410.                      */
  411.                     pimg[width * row + col] = gray;
  412.  
  413.                     src += (zoomflag) ? (col & 1) : 1;
  414.                 }
  415.  
  416.                 if (dlinfo.format)
  417.                 {
  418.                     if (zoomflag)
  419.                     {
  420.                         src += (row & 1) ? 160 : -160;
  421.                     }
  422.                     else
  423.                     {
  424.                         src += 160;
  425.                     }
  426.                 }
  427.             }
  428.  
  429.  
  430.             /*
  431.              *   advance image pointer to next frame
  432.              */
  433.             pimg += pimg_inc;
  434.         }
  435.     }
  436.     if (verbose)
  437.         printf("done.\n"); fflush(stdout);
  438.  
  439.  
  440.  
  441.     /*
  442.      *   Read the commands.
  443.      */
  444.     if (verbose)
  445.         printf("Number of commands is %d\n", dlinfo.num_command);
  446.     for (i = 0; i < dlinfo.num_command; i++)
  447.     {
  448.         if (dlinfo.version == 2)
  449.         {
  450.             j      = fgetc(fp);
  451.             j     += fgetc(fp) << 8;
  452.             cmd[i] = j;
  453.         }
  454.         else
  455.         {
  456.             j      = fgetc(fp);
  457.             cmd[i] = (j % 10) - 1 + ((j / 10) - 1) * 4;
  458.         }
  459.         if (verbose)
  460.             printf("command %3d: %d\n", i, cmd[i]);
  461.     }
  462.     if (verbose)
  463.         fflush(stdout);
  464.  
  465.  
  466.     /*
  467.      *   if last cmd is -ve, it contains the 'labelpos'. what is this?
  468.      */
  469.     labelpos = 0;
  470.     if (isneg16(cmd[dlinfo.num_command - 1]))
  471.     {
  472.         labelpos = (neg16(cmd[dlinfo.num_command - 1]) 
  473.             + 1);            /* Correct? Why add 1 ?? */
  474.         dlinfo.num_command--;        /* ignore that last command */
  475.     }
  476.  
  477.  
  478.  
  479.     /*
  480.      *   do it. first set delay per frame (milliseconds)
  481.      */
  482.     frame_freq = 1000/fps;
  483.  
  484.     dl_flicker (img, nframes, width, height, beta, noise, do_flick,
  485.         frame_freq, cmd, ncommands, verbose);
  486.  
  487.  
  488.     exit (0);
  489. }
  490.  
  491.  
  492.  
  493.  
  494.  
  495. /*------------------------------*/
  496. /*    colormap_setup        */
  497. /*------------------------------*/
  498. void colormap_setup (FILE *fp, int version)
  499. {
  500.  
  501. /*
  502.  *    Initialize the colormap. I use a private one for PseudoColor,
  503.  *    I was too tired to fiddle with allocating shared colors.
  504.  */
  505.  
  506.     unsigned char    pal[768];
  507.     int        i;
  508.  
  509.  
  510.     /*
  511.      *   Is this the border colour? ignore this anyway...
  512.      */
  513.     if (version == 2)
  514.     {
  515.         for (i = 0; i < 3; i++)
  516.             fgetc(fp);
  517.     }
  518.     else
  519.         fgetc(fp);
  520.  
  521.  
  522.     
  523.     /*
  524.      *   Here comes the colormap. 3 bytes per each of 256 colors.
  525.      */
  526.     fread(pal, 1, 768, fp);
  527.  
  528.  
  529.  
  530.     /*
  531.      *   Set up for grayscale conversion on a monochrome display (NTSC
  532.      *   weights). flicker interprets 0 as black and 255 as white.
  533.      *
  534.      *   TODO: consider histogram equalization here...
  535.      */
  536.     for (i = 0; i < 256; i++)
  537.     {
  538.         pixels[i] = (((unsigned long)pal[3*i    ] << 2) * 300) / 1000
  539.               + (((unsigned long)pal[3*i + 1] << 2) * 590) / 1000
  540.               + (((unsigned long)pal[3*i + 2] << 2) * 110) / 1000;
  541.     }
  542.     return;
  543. }
  544.  
  545.  
  546.  
  547. /*------------------------------*/
  548. /*    usage            */
  549. /*------------------------------*/
  550. void usage (int excode)
  551. {
  552.     fprintf(stderr,"usage: %s [options] [file.dl]\n", myname);
  553.     fprintf(stderr,"options:\n");
  554.     fprintf(stderr,"-v       verbose\n");
  555.     fprintf(stderr,"-s       single image (no flicker)\n");
  556.     fprintf(stderr,"-b beta  for laplace filter (0..10)\n");
  557.     fprintf(stderr,"-n noise add random noise (0..255)\n");
  558.     fprintf(stderr,"-z       zoom (enlarge to 320x200)\n");
  559.     fprintf(stderr,"-h       help\n");
  560.     fprintf(stderr,"-i val   add value to pixel intensity (-255..255)\n");
  561.     fprintf(stderr,"-r fps   run at fps frames/second (default=25)\n");
  562.  
  563.     exit (excode);
  564. }
  565.  
  566.